#include <string.h>
#include <iostream>
using namespace std;

// 右值就是没有办法直接取地址的值
class String{
public:
    String()
    :_pstr(new char[1]())
    {
        cout << "String()" << endl;
    }
    // 构造函数
    String(const char * pstr)
    :_pstr(new char[strlen(pstr) + 1]())
    {
        strcpy(_pstr,pstr);
        cout << "String(const char *)" << endl;
    }

    // 拷贝构造函数
    String(const String & rhs)
    :_pstr(new char[strlen(rhs._pstr) + 1]())
    {   
        strcpy(_pstr, rhs._pstr);
        cout << "String(const String &)" << endl;
    }
    // 右值引用拷贝构造 移动拷贝构造函数
    String(String && rhs)
    // 直接把指向内存空间的指针地址复制过来
    // 这样拷贝构造的函数的指针指向
    // 指向的就是右值的（临时变量）的内存地址
    // 直接进行浅拷贝，然后把临时变量指针销毁
    // 这样就实现了移动语义
    :_pstr(rhs._pstr)
    {   
        rhs._pstr = nullptr; 
        cout << "String(String &&)" << endl;
    }

    // 赋值运算符函数
    String & operator=(const  String & rhs){
        if(this != &rhs){
            delete [] _pstr;
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }
        return *this;
    }

    // 右值赋值运算符函数
    String  & operator=(String && rhs){
        // 右值赋值运算需不需要考虑自赋值
        // 需要！！ 后面的std::move()就是有字赋值的情况
        if(this != &rhs){
            delete [] _pstr; // 释放原来内存
            _pstr = rhs._pstr; // 改变指针指向新的内存
            rhs._pstr = nullptr; // 将临时对象指针销毁
        }
        cout << "Strinf &operator(String &&)" << endl;
        return *this;
    }


private:
    char * _pstr;
};

void test(){

    String s1("hello");// 构造函数左值
    String s2("word");// 构造函数左值
    String s3 = s2; // 都是左值直接调用拷贝构造函数
    String s4("ni");
    s4 = s3;// 都是左值赋值运算符
    cout << "====下面使用右值函数====" << endl;
    String s5 = String("C++yes");// 调用右值拷贝构造运算符
    s1 = String("nihao");

}

int main(int atgc, char * argv[])
{
    test();
    return 0;
}

